import React, { useCallback, useEffect, useState } from 'react';
import { poiSearch, queryDanmaku } from '@/api';
import { findAllMarker, IApiFindAllMarkerResult, IApiQueryDanmakuResult, IApiTDTSearchData, IApiTDTSearchRes } from '@/api';

type IApiHooksResult<R = any> = {
  result?: R;
  status?: 'loading' | 'loaded' | 'error';
};

type IApiHooksProps<P = any, R = any> = {
  params?: P;
  id: string;
  fn: (params: P) => Promise<R>;
  deps?: React.DependencyList;
  intercept?: {
    response?: (res: R) => R;
  };
};

const useApi = <R = any, P = any>(props: IApiHooksProps<P>) => {
  const { fn, id, params, deps = [], intercept } = props ?? {};
  const [state, setState] = useState<IApiHooksResult<R>>();

  const run = useCallback(async (params: P, options?: { silent?: boolean }): Promise<R | undefined> => {
    const { silent } = options ?? {};
    try {
      if (!silent) setState({ status: 'loading' });
      const res = await fn(params);
      const result = intercept?.response?.(res) ?? res?.data;
      if (!silent) setState({ status: 'loaded', result });
      return result;
    } catch (e) {
      console.error(`${id} error: `, e);
      if (!silent) setState((prev) => ({ ...prev, status: 'error' }));
    }
    return;
  }, []);

  useEffect(() => {
    if (params) run(params);
  }, deps);

  return { ...state, run };
};

export const useApiQueryDanmaku = (props?: Omit<IApiHooksProps<Parameters<typeof queryDanmaku>[0]>, 'id' | 'fn'>) => {
  return useApi<IApiQueryDanmakuResult, Parameters<typeof queryDanmaku>[0]>({
    id: 'quueryDanmaku',
    fn: queryDanmaku,
    ...props,
  });
};

export const useApiPoiSearch = (props?: Omit<IApiHooksProps<Parameters<typeof poiSearch>[0]>, 'id' | 'fn'>) => {
  return useApi<IApiTDTSearchRes<IApiTDTSearchData>, Parameters<typeof poiSearch>[0]>({ id: 'poiSearch', fn: poiSearch, ...props });
};

export const useApiFindAllMarker = (props?: Omit<IApiHooksProps, 'id' | 'fn'>) => {
  return useApi<IApiFindAllMarkerResult>({ id: 'findAllMarker', fn: findAllMarker, intercept: { response: (res) => res }, ...props });
};
